package entities;

import game.Level;

import java.awt.geom.Rectangle2D;
import java.util.Random;

import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;

import util.Vector2D;

public abstract class Entity {

	protected static Random random = new Random();

	protected int maxHealth;
	protected int health;
	protected int score;

	protected Vector2D pos;
	protected Vector2D velocity;
	protected Vector2D acceleration;
	protected float friction;

	protected Image image;

	protected Level level;

	protected boolean alive;

	/**
	 * 
	 * @param coordX
	 *            x coordinate of coord
	 * @param coordY
	 *            y coordinate of coord
	 * @throws SlickException
	 */
	public Entity(String imagePath) throws SlickException {
		this.image = new Image(imagePath);
		this.maxHealth = 1;
		this.friction = 0.0f;
		reset();
	}

	public void spawn(Level level, Vector2D pos) {
		if (level != null) {
			this.level = level;
			level.addEntity(this);
			setPosition(pos);
		}
	}

	public void setVelocity(Vector2D v) {
		this.velocity = v;
	}

	protected void move(Vector2D delta) {
		pos = pos.add(delta);
	}

	public Vector2D getAcceleration() {
		return acceleration;
	}

	public int getScore() {
		return score;
	}

	public void setAcceleration(Vector2D a) {
		this.acceleration = a;
	}

	public Vector2D getPosition() {
		return pos;
	}

	public void setPosition(float x, float y) {
		setPosition(new Vector2D(x, y));
	}

	public void setPosition(Vector2D pos) {
		this.pos = pos;
	}

	public Image getImage() {
		return image;
	}

	public float getX() {
		return pos.getX();
	}

	public float getY() {
		return pos.getY();
	}

	public Vector2D center() {
		return new Vector2D(pos.getX() + (image.getWidth() / 2), pos.getY()
				+ (image.getHeight() / 2));
	}

	public void update(GameContainer gc, int delta) {
		if (!isAlive()) {
			level.removeEntity(this);
		}
		Vector2D dv = acceleration.scale(delta / 1000.0f);
		velocity = velocity.add(dv);
		velocity = velocity.scale(1.0f - ((friction) * (delta / 1000.0f)));
		pos = pos.add(velocity.scale(delta / 1000.0f));
		checkEntityPosition(gc);
	}

	public void render(GameContainer gc, Graphics g) {
		g.drawImage(image, getX(), getY());
//		g.setColor(Color.red);
//		Rectangle2D hitbox = getHitbox();
//		g.drawRect((float) hitbox.getX(), (float) hitbox.getY(),
//				(float) hitbox.getWidth(), (float) hitbox.getHeight());
	}

	public void takeDamage(int damage) {
		health = Math.max(health - damage, 0);
	}

	public void flipImage() {
		image = image.getFlippedCopy(true, false);
	}

	public boolean collidesWith(Entity e) {
		return isAlive() && e.isAlive()
				&& e.getHitbox().intersects(getHitbox());
	}

	public Rectangle2D getHitbox() {
		return new Rectangle2D.Float(getX(), getY(), image.getWidth(),
				image.getHeight());
	}

	public boolean isAlive() {
		return health > 0;
	}

	public void reset() {
		alive = true;
		velocity = Vector2D.ZERO_VECTOR;
		acceleration = Vector2D.ZERO_VECTOR;
		health = maxHealth;
	}

	public abstract String getName();

	public abstract void checkEntityPosition(GameContainer gc);
}
